package org.steven.crm.core.utils;

import java.util.Calendar;

public class IdCard {
	private String idCardNum = null;
	
	private static int IS_EMPTY = 1;
	private static int LEN_ERROR = 2;
	private static int CHAR_ERROR = 3;
	private static int DATE_ERROR = 4;
	private static int CHECK_BIT_ERROR = 5;
	
	public static String[] errMsg = new String[] {"身份证完全正确！", 
			"身份证为空！", 
			"身份证长度不正确！", 
			"身份证有非法字符！", 
			"身份证中出生日期不合法！", 
	"身份证校验位错误！"};
	
	private int error = 0;
	
	/**
	 * 构造方法。
	 * @param idCardNum
	 */
	public IdCard(String idCardNum) {
		// super();
		this.idCardNum = idCardNum.trim();
	}
	
	public String getIdCardNum() {
		return idCardNum;
	}
	
	public void setIdCardNum(String idCardNum) {
		this.idCardNum = idCardNum;
	}
	
	/**
	 * 得到身份证详细错误信息。
	 * @return 错误信息。
	 */
	public String getErrMsg(){
		return errMsg[this.error];
	}
	
	/**
	 * 是否为空。
	 * @return true: null  false: not null;
	 */
	public boolean isEmpty(){
		if(this.idCardNum==null)
			return true;
		else
			return this.idCardNum.trim().length()>0 ? false:true;
	}
	
	/**
	 * 身份证长度。
	 * @return
	 */
	public int getLength(){
		return this.isEmpty() ? 0:this.idCardNum.length();
	}
	
	/**
	 * 身份证长度。
	 * @return
	 */
	public int getLength(String str){
		return this.isEmpty() ? 0:str.length();
	}
	
	/**
	 * 是否是15位身份证。
	 * @return true: 15位  false：其他。
	 */
	public boolean is15(){
		return this.getLength()==15;
	}
	
	/**
	 * 是否是18位身份证。
	 * @return true: 18位  false：其他。
	 */
	public boolean is18(){
		return this.getLength()==18;
	}
	
	/**
	 * 得到身份证的省份代码。
	 * @return 省份代码。
	 */
	public String getProvince(){
		return this.isCorrect()==0 ? this.idCardNum.substring(0,2):"";
	}
	
	/**
	 * 得到身份证的城市代码。
	 * @return 城市代码。
	 */
	public String getCity(){
		return this.isCorrect()==0 ? this.idCardNum.substring(2,4):"";
	}
	
	/**
	 * 得到身份证的区县代码。
	 * @return 区县代码。
	 */
	public String getCountry(){
		return this.isCorrect()==0 ? this.idCardNum.substring(4,6):"";
	}
	
	/**
	 * 得到身份证的出生年份。
	 * @return 出生年份。
	 */
	public String getYear(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.getLength()==15){
			return "19"+this.idCardNum.substring(6,8);
		}else{
			return this.idCardNum.substring(6,10);
		}
	}
	
	/**
	 * 得到身份证的出生月份。
	 * @return 出生月份。
	 */
	public String getMonth(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.getLength()==15){
			return this.idCardNum.substring(8,10);
		}else{
			return this.idCardNum.substring(10,12);
		}
	}
	
	/**
	 * 得到身份证的出生日子。
	 * @return 出生日期。
	 */
	public String getDay(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.getLength()==15){
			return this.idCardNum.substring(10,12);
		}else{
			return this.idCardNum.substring(12,14);
		}
	}
	
	/**
	 * 得到身份证的出生日期。
	 * @return 出生日期。
	 */
	public String getBirthday(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.getLength()==15){
			return "19"+this.idCardNum.substring(6,12);
		}else{
			return this.idCardNum.substring(6,14);
		}
	}
	/**
	 * 得到身份证的出生年月。
	 * @return 出生年月。
	 */
	public String getBirthMonth(){
		return getBirthday().substring(0, 6);
	}
	/**
	 * 得到身份证的顺序号。
	 * @return 顺序号。
	 */
	public String getOrder(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.getLength()==15){
			return this.idCardNum.substring(12,15);
		}else{
			return this.idCardNum.substring(14,17);
		}
	}
	
	/**
	 * 得到性别。
	 * @return 性别：1－男  2－女
	 */
	public String getSex(){
		if(this.isCorrect()!=0)
			return "";
		
		int p=Integer.parseInt(getOrder());
		if(p%2==1){
			return "男";
		}else{
			return "女";
		}
	}
	/**
	 * 得到性别值。
	 * @return 性别：1－男  2－女
	 */
	public String getSexValue(){
		if(this.isCorrect()!=0)
			return "";
		
		int p=Integer.parseInt(getOrder());
		if(p%2==1){
			return "1";
		}else{
			return "2";
		}
	}
	
	/**
	 * 得到校验位。
	 * @return 校验位。
	 */
	public String getCheck(){
		if(!this.isLenCorrect())
			return "";
		
		if(this.getLength()==18)
			return this.idCardNum.substring(17);
		else
			return this.getCheckBit();
	}
	
	/**
	 * 得到15位身份证。
	 * @return 15位身份证。 
	 */
	public String to15(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.is15())
			return this.idCardNum;
		else
			return this.idCardNum.substring(0, 6)+this.idCardNum.substring(8,17);
	}
	
	/**
	 * 得到18位身份证。
	 * @return 18位身份证。
	 */
	public String to18(){
		if(this.isCorrect()!=0)
			return "";
		
		if(this.is18())
			return this.idCardNum;
		else
			return this.idCardNum.substring(0, 6)+"19"+this.idCardNum.substring(6)+this.getCheckBit();
	}
	
	/**
	 * 得到18位身份证。
	 * @return 18位身份证。
	 */
	public static String toNewIdCard(String tempStr){
		if(tempStr.length()==18)
			return tempStr.substring(0, 6)+tempStr.substring(8,17);
		else
			return tempStr.substring(0, 6)+"19"+tempStr.substring(6)+getCheckBit(tempStr);
	}
	
	/**
	 * 校验身份证是否正确
	 * @return 0：正确
	 */
	public int isCorrect(){
		if(this.isEmpty()){
			this.error=IdCard.IS_EMPTY;
			return this.error; 
		}
		
		if(!this.isLenCorrect()){
			this.error=IdCard.LEN_ERROR;
			return this.error;
		}
		
		if(!this.isCharCorrect()){
			this.error=IdCard.CHAR_ERROR;
			return this.error;
		}
		
		if(!this.isDateCorrect()){
			this.error=IdCard.DATE_ERROR;
			return this.error;
		}
		
		if(this.is18()){
			if(!this.getCheck().equals(this.getCheckBit())){
				this.error=IdCard.CHECK_BIT_ERROR;
				return this.error;
			}
		}
		if(this.is15()){
			if(!this.getCheck().equals(this.getCheckBit())){
				this.error=IdCard.CHECK_BIT_ERROR;
				return this.error;
			}
		}
		
		return 0;
	}
	
	
	private boolean isLenCorrect(){
		return this.is15()||this.is18();
	}
	
	/**
	 * 判断身份证中出生日期是否正确。
	 * @return
	 */
	private boolean isDateCorrect(){
		
		/*非闰年天数*/
		int[] monthDayN={31,28,31,30,31,30,31,31,30,31,30,31};
		/*闰年天数*/
		int[] monthDayL={31,29,31,30,31,30,31,31,30,31,30,31};
		
		int month;
		if(this.is15()){
			month=Integer.parseInt(this.idCardNum.substring(8,10));
		}else{
			month=Integer.parseInt(this.idCardNum.substring(10,12));
		}
		
		if(month>12 || month<=0){
			return false;
		}
		
		int day;
		if(this.is15()){
			day=Integer.parseInt(this.idCardNum.substring(10,12));
		}else{
			day=Integer.parseInt(this.idCardNum.substring(12,14));
		}
		
		if(this.isLeapyear()){
			if(day>monthDayL[month-1] || day<=0)
				return false;
		}else{
			if(day>monthDayN[month-1] || day<=0)
				return false;
		}
		
		return true;
	}
	
	/**
	 * 得到校验位。
	 * @return
	 */
	private String getCheckBit() {
		if(!this.isLenCorrect())
			return "";
		
		String temp = null;
		if(this.is18())
			temp=this.idCardNum;
		else
			temp=this.idCardNum.substring(0, 6)+"19"+this.idCardNum.substring(6);
		
		
		String checkTable[] = new String[] {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
		int[] wi = new int[]{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1};
		int sum=0;
		
		for(int i=0; i<17; i++){
			String ch = temp.substring(i,i+1);
			sum = sum + Integer.parseInt(ch)*wi[i];
		}
		
		int y = sum % 11;
		
		return checkTable[y];
	}
	
	
	/**
	 * 得到校验位。
	 * @return
	 */
	private static String getCheckBit(String str) {
		
		String temp = null;
		if(str.length()==18)
			temp=str;
		else
			temp=str.substring(0, 6)+"19"+str.substring(6);
		
		
		String checkTable[] = new String[] {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
		int[] wi = new int[]{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1};
		int sum=0;
		
		for(int i=0; i<17; i++){
			String ch = temp.substring(i,i+1);
			sum = sum + Integer.parseInt(ch)*wi[i];
		}
		
		int y = sum % 11;
		
		return checkTable[y];
	}
	
	
	/**
	 * 身份证号码中是否存在非法字符。
	 * @return true: 正确  false：存在非法字符。
	 */
	private boolean isCharCorrect(){
		boolean iRet=true;
		
		if(this.isLenCorrect()){
			byte[] temp = this.idCardNum.getBytes();
			
			if(this.is15()){
				for(int i=0; i<temp.length; i++){
					if(temp[i]<48 || temp[i]>57){
						iRet=false;
						break;
					}   
				}
			}
			
			if(this.is18()){
				for(int i=0; i<temp.length; i++){
					if(temp[i]<48 || temp[i]>57){
						if(i==17 && temp[i]!=88){
							iRet=false;
							break;
						}
					}   
				}
			}
		}else{
			iRet=false;
		}
		return iRet;
	}
	/**
	 * 判断身份证的出生年份是否未闰年。
	 * @return  true ：闰年  false 平年
	 */
	private boolean isLeapyear(){
		String temp;
		
		if(this.is15()){
			temp="19"+this.idCardNum.substring(6,8);
		}else{
			temp=this.idCardNum.substring(6,10);
		}
		
		int year=Integer.parseInt(temp);
		
		if ((year%4 == 0 &&  year%100 != 0) || year%400 == 0)
			return true;
		else
			return false;
	}
	
	public static void main(String[] args) {
		IdCard test = new IdCard("452123198509112550");
		System.out.println(test.isCorrect());
	}
	
	public String getAge() { 
		//截取身份证中出行人出生日期中的年、月、日 
		Integer personYear = Integer.parseInt(idCardNum.substring(6, 10)); 
		Integer personMonth = Integer.parseInt(idCardNum.substring(10, 12)); 
		Integer personDay = Integer.parseInt(idCardNum.substring(12, 14)); 
		Calendar cal = Calendar.getInstance(); // 得到当前时间的年、月、日 
		Integer yearNow = cal.get(Calendar.YEAR); 
		Integer monthNow = cal.get(Calendar.MONTH) + 1; 
		Integer dayNow = cal.get(Calendar.DATE); // 用当前年月日减去生日年月日 
		Integer yearMinus = yearNow - personYear; 
		Integer monthMinus = monthNow - personMonth; 
		Integer dayMinus = dayNow - personDay; 
		Integer age = yearMinus; //先大致赋值 
		if (yearMinus == 0) { //出生年份为当前年份 
			age = 0; 
		} else { //出生年份大于当前年份 
			if (monthMinus < 0) {
				//出生月份小于当前月份时，还没满周岁 
				age = age - 1; 
			} if (monthMinus == 0) {//当前月份为出生月份时，判断日期 
				if (dayMinus < 0) {//出生日期小于当前月份时，没满周岁 
					age = age - 1; 
				} 
			} 
		}
		return age + ""; 
	}
}
